#include "powerbus.h"
#include "ui_powerbus.h"
#include <QDateTime>
#include <QDebug>
#include <QMessageBox>

#include "pmbus_parse.h"
#include <boost/algorithm/hex.hpp>
#include <boost/algorithm/string.hpp>

PowerBus::PowerBus(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::PowerBus)
{
    ui->setupUi(this);

    m_serialState = false;

    ui->cbBiteRate->setCurrentIndex(3);
    ui->cbDataBit->setCurrentIndex(3);
    m_pDecoupler = new CFensDecoupler("\x7E", "\x0D");

    QRegExp regExp("[a-fA-F0-9][a-fA-F0-9]");
    QValidator *validator_v = new QRegExpValidator(regExp, ui->ver);
    ui->ver->setValidator(validator_v);
    QValidator *validator_a = new QRegExpValidator(regExp, ui->addr);
    ui->addr->setValidator(validator_a);
    QValidator *validator_c1 = new QRegExpValidator(regExp, ui->cd1);
    ui->cd1->setValidator(validator_c1);
    QValidator *validator_c2 = new QRegExpValidator(regExp, ui->cd2);
    ui->cd2->setValidator(validator_c2);

    m_pSerial = new QSerialPort;
    connect(m_pSerial, &QSerialPort::readyRead, this , &PowerBus::OnReadData);

    setWindowTitle("电总协议串口调试助手 风正致远信息技术股份有限公司 http://www.fzzygf.com");
}

PowerBus::~PowerBus()
{
    delete m_pSerial;
    delete m_pDecoupler;

    delete ui;
}

void PowerBus::SetCbEnable(bool flag)
{
    ui->comName->setEnabled(flag);
    ui->cbBiteRate->setEnabled(flag);
    ui->cbDataBit->setEnabled(flag);
    ui->cbStopBit->setEnabled(flag);
    ui->cbCheck->setEnabled(flag);
}

bool PowerBus::OpenSerial()
{
    //设置串口名
    m_pSerial->setPortName(ui->comName->currentText());

    //设置波特率
    m_pSerial->setBaudRate(ui->cbBiteRate->currentText().toInt());

    //设置数据位数
    switch (ui->cbDataBit->currentText().toInt())
    {
    case 8:
        m_pSerial->setDataBits(QSerialPort::Data8);
        break;
    case 7:
        m_pSerial->setDataBits(QSerialPort::Data7);
        break;
    case 6:
        m_pSerial->setDataBits(QSerialPort::Data6);
        break;
    case 5:
        m_pSerial->setDataBits(QSerialPort::Data5);
        break;
    default:
        break;
    }

    //设置校验位
    switch (ui->cbCheck->currentIndex())
    {
    case 0:
        m_pSerial->setParity(QSerialPort::NoParity);
        break;
    case 1:
        m_pSerial->setParity(QSerialPort::EvenParity);
        break;
    case 2:
        m_pSerial->setParity(QSerialPort::OddParity);
        break;
    default:
        break;
    }
    //设置停止位
    switch (ui->cbStopBit->currentText().toInt())
    {
    case 1:
        m_pSerial->setStopBits(QSerialPort::OneStop);
        break;
    case 2:
        m_pSerial->setStopBits(QSerialPort::TwoStop);
    default:
        break;
    }
    //设置流控制
    m_pSerial->setFlowControl(QSerialPort::NoFlowControl);

    //打开串口
    bool ret = m_pSerial->open(QIODevice::ReadWrite);
    if( !ret )
    {
        qDebug()<<"open "<<ui->comName->currentText()<<" error";
        ui->msg->setText(tr("打开串口:")+ui->comName->currentText()+tr("失败"));
        return false;
    }

    m_serialState = true;
    ui->msg->setText("打开串口成功");

    return true;
}

void PowerBus::on_btOpen_clicked()
{
    if ( m_serialState ) return;
    if ( !OpenSerial() )
    {
        ui->msg->setText("打开串口"+ui->comName->currentText()+"失败!");
        return;
    }

    ui->btOpen->setEnabled(false);
    ui->btClose->setEnabled(true);
    SetCbEnable(false);
}

void PowerBus::on_btClose_clicked()
{
    if(!m_serialState) return;
    m_serialState = false;
    ui->btClose->setEnabled(false);
    ui->btOpen->setEnabled(true);
    SetCbEnable(true);

    //关闭串口
    m_pSerial->clear();
    m_pSerial->close();
    ui->msg->setText("串口已关闭");
}

//清空显示区域
void PowerBus::on_btClear_clicked()
{
    ui->textEdit->clear();
}

std::string PowerBus::CheckInput(const QString &input)
{
    std::string tmp = input.toStdString();
    if ( input.size() == 1 )
    {
        tmp = "0"+input.toStdString();
    }

    return tmp;
}

void PowerBus::on_btSend_clicked()
{
    if (!m_serialState)
    {
        ui->msg->setText("串口未打开, 请先打开串口!");
//        return;
    }

    string msg;

    std::string hexData = boost::algorithm::unhex(CheckInput(ui->ver->text()));
    int ver = hexData.at(0);
    hexData = boost::algorithm::unhex(CheckInput(ui->addr->text()));
    uint8_t addr = hexData.at(0);
    hexData = boost::algorithm::unhex(CheckInput(ui->cd1->text()));
    uint8_t cd1 = hexData.at(0);
    hexData = boost::algorithm::unhex(CheckInput(ui->cd2->text()));
    uint8_t cd2 = hexData.at(0);

    qDebug()<<"ver: "<<ver<<", addr: "<<addr<<", cd1: "<<cd1<<", cd2: "<<cd2<<", data: "<<ui->sendText->toPlainText().toLocal8Bit();

    hexData.clear();
    if ( !ui->sendText->toPlainText().isEmpty() )
    {
        QByteArray buf;
        int ret = Ascii2Hex(ui->sendText->toPlainText().toLocal8Bit(),buf);
        if (ret == -1)
        {
            QMessageBox::warning(this, tr("提示"), tr("请检查数据发送区数据~"));
            return;
        }

        hexData = buf.toStdString();
    }

    pmbus_package_cmd(ver, addr, cd1, cd2, msg, hexData);

    WriteData(QByteArray::fromStdString(msg));

}

void PowerBus::OnReadData()
{
    QByteArray msg;
    msg = m_pSerial->readAll();

    m_pDecoupler->Put(msg.toStdString());
    string OneMsg;

    while( m_pDecoupler->Get(OneMsg) == 0 )
    {
       // qDebug()<<"recv svr data size: "<<OneMsg.size();

        QDateTime dateTime;
        QString qstrTime= dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");

        msg.clear();
        InsertSpace(QByteArray::fromStdString(OneMsg).toHex(), msg);
        ui->textEdit->append("<span style=\" color:blue;\">["+qstrTime+"][接收]: "+msg+ "("+QByteArray::fromStdString(OneMsg)+")"+"</span>");
        //process data
        OneMsg.clear();
    }
}

void PowerBus::InsertSpace(const QByteArray& src, QByteArray &dest)
{
    for (int i = 0; i < src.size(); i++ )
    {
        dest.append(src.at(i));
        if (i % 2) dest.append(0x20);
    }
}

//发送数据，同时将数据显示在提示框里
int PowerBus::WriteData(const QByteArray &data)
{
    if (data.isEmpty()) return 0;

    QDateTime dateTime;
    QString qstrTime= dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
    QByteArray msgText ;
    InsertSpace(data.toHex(), msgText);
    ui->textEdit->append("<span style=\" color:red;\">["+qstrTime+"][发送]: "+msgText + "("+data+")"+"</span>");

    if ( !m_pSerial->isOpen() )
    {
        ui->msg->setText("串口未打开，请先打开串口~");
        return -1;
    }

    m_pSerial->write(data);

    return 0;
}

//ascii转换为hex
int PowerBus::Ascii2Hex(const QByteArray &inData, QByteArray &outData)
{
    QByteArray::const_iterator itr1;
    QByteArray tmpData = inData;

    while (tmpData.indexOf("\x20") > 0)   //去掉空格
    {
        tmpData.remove(tmpData.indexOf("\x20"),1);
    }

    int outIndex = 0;
    itr1 = tmpData.begin();
    char tmpData_h = 0, tmpData_l = 0;
    for( outIndex = 0; outIndex != tmpData.size()/2; outIndex++)
    {
        if(itr1 != tmpData.end())
        {
            if(*itr1 <= '9' &&  *itr1 >= '0')
               tmpData_h = *itr1 - 0x30;
            else if(*itr1 <= 'F' &&  *itr1 >= 'A')
               tmpData_h = *itr1 - 'A' + 0xA;
            else if(*itr1 <= 'f' &&  *itr1 >= 'a')
               tmpData_h = *itr1 - 'a' + 0xA;
            else
                return -1;
        }
        itr1++;
        if(itr1 != tmpData.end())
        {
            if(*itr1 <= '9' &&  *itr1 >= '0')
               tmpData_l = *itr1 - 0x30;
            else if(*itr1 <= 'F' &&  *itr1 >= 'A')
               tmpData_l = *itr1 - 'A' + 0xA;
            else if(*itr1 <= 'f' &&  *itr1 >= 'a')
               tmpData_l = *itr1 - 'a' + 0xA;
            else
                return -1;
        }
        itr1++;
        outData.append((tmpData_h << 4) | (tmpData_l & 0x0f));
    }

    return 0;
}
